package com.cgg.java8.ch02;

import com.cgg.java8.entity.Apple;
import com.cgg.java8.utils.Utils;
import org.junit.Test;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author Xiecheng create on 2021/9/14
 * 
 * 复合lambda，用于将多个lambda表达式组合
 */
public class Demo03 {
    // ～～～～～～～～～～～～～～～～～～～～～～～～～～比较器的复合玩法 通过reversed, thenComparing

    /**
     * 升序和降序
     */
    @Test
    public void testCompare1() {
        List<Apple> apples = Arrays.asList(
                new Apple("green", 150),
                new Apple("red", 90),
                new Apple("pink", 260),
                new Apple("yellow", 180)
        );
        // 按照重量排序ASC
        apples.sort(Comparator.comparingInt(Apple::getWeight));
        Utils.printListAsJson(apples);

        // 按重量逆序排序. 通过reversed()进行组合。
        apples.sort(Comparator.comparingInt(Apple::getWeight).reversed());
        Utils.printListAsJson(apples);
    }

    /**
     * 比较器的组合. 用于第一个比较器结果相等的情况
     */
    @Test
    public void testCompare2() {
        List<Apple> apples = Arrays.asList(
                new Apple("green", 150),
                new Apple("red", 90),
                new Apple("pink", 260),
                new Apple("yellow", 150)
        );
        // 先按照重量降序排序， 在按照颜色排序
        apples.sort(Comparator.comparingInt(Apple::getWeight).reversed().thenComparing(Apple::getColor));
        Utils.printListAsJson(apples);
    }

    // ～～～～～～～～～～～～～～～～～～～～～～～～～～谓词组合玩法negate, and, or
    @Test
    public void testPredicate1() {
        List<Apple> apples = Arrays.asList(
                new Apple("green", 150),
                new Apple("red", 90),
                new Apple("pink", 260),
                new Apple("yellow", 150)
        );
        // 找到不是pink苹果的集合
        final Predicate<Apple> pre = a -> a.getColor().equals("pink");
        final Predicate<Apple> condition = pre.negate();
        final List<Apple> collect = apples.stream().filter(condition).collect(Collectors.toList());
        Utils.printListAsJson(collect);
    }

    @Test
    public void testPredicate2() {
        List<Apple> apples = Arrays.asList(
                new Apple("green", 280),
                new Apple("red", 290),
                new Apple("pink", 120),
                new Apple("yellow", 50)
        );
        // 找到又大（200+）又红的苹果
        Predicate<Apple> big = a -> a.getWeight() > 200;
        final Predicate<Apple> bigAndRed = big.and(a -> a.getColor().equals("red"));
        final List<Apple> collect = apples.stream().filter(bigAndRed).collect(Collectors.toList());
        System.out.println("--> 又大又红的苹果");
        Utils.printListAsJson(collect);

        // 找到小(150-)苹果或者绿苹果
        Predicate<Apple> small = a -> a.getWeight() < 150;
        Predicate<Apple> smallOrGreen = small.or(a -> a.getColor().equals("green"));
        System.out.println("--> 小苹果或者绿苹果");
        Utils.printListAsJson(apples.stream().filter(smallOrGreen).collect(Collectors.toList()));

    }

    // ～～～～～～～～～～～～～～～～～～～～～～～～～～函数Function复合的玩法: andThen, compose

    // andThen可以看作是流水线的处理， a.andThen(b). 先a，然后把a的结果传入到b进行处理
    // a.compose(b)则是 先进行b， 把b处理的结果交给a处理
    @Test
    public void testFunction1() {
        Function<Integer, Integer> plus = x -> x + 1;
        Function<Integer, Integer> multiplication = x -> 3 * x;
        // 一个数先 + 1， 然后 * 3
        final Integer result = plus.andThen(multiplication).apply(10);
        System.out.println(result);
    }

    @Test
    public void testFunction2() {
        Function<Integer, Integer> plus = x -> x + 1;
        Function<Integer, Integer> multiplication = x -> 3 * x;
        // 一个数先 * 3, 再 + 1
        final Integer result = plus.compose(multiplication).apply(10);
        System.out.println(result);
    }
}
